<?php

namespace App\Controller\Api\User;

use App\Algorithm\ScheduleAlgorithm;
use App\Constants\ErrorCode;
use App\Controller\Api\BaseController;
use App\Model\ConsultantDatum;
use App\Model\ConsultantGood;
use App\Model\ExchangeRate;
use App\Model\Order;
use App\Model\OrderGood;
use App\Model\OrderReservation;
use App\Model\OrderReview;
use App\Model\PayMethodTran;
use App\Model\ReviewLabelTran;
use App\Model\User;
use App\Model\UserDatum;
use App\Model\WorkDate;
use App\Model\WorkReservation;
use App\Service\OrderService;
use App\Service\WorkService;
use Hyperf\DbConnection\Db;
use Hyperf\Di\Annotation\Inject;
use Hyperf\HttpServer\Annotation\Controller;
use Hyperf\HttpServer\Annotation\Middleware;
use App\Middleware\JWTAuthMiddleware;
use Hyperf\HttpServer\Annotation\RequestMapping;
use Psr\Http\Message\ResponseInterface;

/**
 * @Middleware(JWTAuthMiddleware::class)
 * @Controller(prefix="/user/v1/order")
 */
class OrderController extends BaseController
{


    /**
     * @Inject()
     * @var ScheduleAlgorithm
     */
    public $scheduleAlgorithm;

    /**
     * @Inject()
     * @var OrderService
     */
    public $orderService;


    /**
     * @Inject()
     * @var WorkService
     */
    public $workService;


    /**
     * 咨询师下单初始信息
     * @RequestMapping(path="goodsInfo")
     * @return ResponseInterface
     */
    public function goodsInfo()
    {
        $id = $this->request->query('id');
        $consultantInfo = ConsultantDatum::from('user as a')
            ->leftJoin('user_datum as b', 'a.id', '=', 'b.uid')
            ->leftJoin('consultant_datum as c', 'a.id', '=', 'c.uid')
            ->leftJoin('country as d', 'c.country', '=', 'd.id')
            ->leftJoin('consultant_goods as e', 'e.uid', '=', 'a.id')
            ->select(['b.uid', 'a.num', 'b.head', 'b.nickname', 'c.type', 'c.language', 'd.country_img', 'e.id as goodsId', 'e.duration', 'e.currency', 'e.price'])
            ->where(['a.id' => $id])
            ->first();

        if (!$consultantInfo) {
            return $this->response->returnFail();
        }
        $consultantInfo = $consultantInfo->toArray();


        //转换货币

        $userCurrency = UserDatum::where(['uid' => $this->uid()])->value('currency');


        $consultantInfo['userCurrency'] = $userCurrency;
        $consultantInfo['userCurrencyPrefix'] = currencyPrefix($userCurrency);

        //货币不同进行 换汇
        if ($userCurrency != $consultantInfo['currency']) {

            $consultantInfo['userPrice'] = (string)ExchangeRate::exchangePrice($userCurrency, $consultantInfo['currency'], $consultantInfo['price']);

        }

        //组装价格字符串数据
        if ($userCurrency == 'CNY') {
            $consultantInfo['priceStr'] = '￥' . $consultantInfo['userPrice'] . '/' . $consultantInfo['duration'] . ' min';
        } else {
            $consultantInfo['priceStr'] = '$' . $consultantInfo['userPrice'] . '/' . $consultantInfo['duration'] . ' min';
        }


        $workDateList = WorkDate::workDateList($id);

        if (empty($workDateList)) {
            return $this->response->returnFail();
        }
        $firstScheduling = null;
        if (!empty($workDateList[0]['info'])) {
            $firstScheduling = $this->workService->scheduling($workDateList[0]['info']['id']);
        }

        $payMethodList = PayMethodTran::where(['lang' => getLang()])->select(['pay_method_id as id', 'name', 'url'])->get()->toArray();

        $data = [
            'consultantInfo' => $consultantInfo,
            'workDateList' => $workDateList,
            'firstScheduling' => $firstScheduling,
            'payMethodList' => $payMethodList
        ];


        return $this->response->returnSuccess(['info' => $data]);


    }


    /**
     * 咨询师排班
     * @RequestMapping(path="workDataList")
     * @return ResponseInterface
     */
    public function workDataList()
    {
        $id = $this->request->query('id');
        $workDateList = WorkDate::workDateList($id);
        return $this->response->returnSuccess(['list' => $workDateList]);
    }


    /**
     * @RequestMapping(path="scheduling")
     * @return ResponseInterface
     */
    public function scheduling()
    {

        $wid = $this->request->query('wid');

        $list = $this->workService->scheduling($wid);

        return $this->response->returnSuccess(['list' => $list]);

    }


    /**
     * 购买课程预下单
     * @RequestMapping(path="buyCoursesPre")
     */
    public function buyCoursesPre()
    {
        $params = $this->request->query();

        $this->validate($params, [
            'id' => 'required',
            'goodsId' => 'required',
            'num' => 'required',
//            'payMethod' => 'required',
//            'chatType' => 'required',
//            'wid' => 'required',
//            'start' => 'required',
//            'end' => 'required'
        ]);


        $goodsInfo = ConsultantGood::where(['id' => $params['goodsId'], 'uid' => $params['id']])->first();
        if (is_null($goodsInfo)) {
            return $this->response->returnFail();
        }


        //暂时不考虑优惠

        $price = (string)round($params['num'] * $goodsInfo['price'], 2);
        $userCurrency = UserDatum::where(['uid' => $this->uid()])->value('currency');
        $currency = $goodsInfo['currency'];
        $data['currency'] = $currency;
        $data['price'] = $price;
        $usePrice = (string)ExchangeRate::exchangePrice($userCurrency, $currency, $price);


        $data['userCurrency'] = $userCurrency;
        $data['userPrice'] = $usePrice;

        $data['userCurrencyPrefix'] = currencyPrefix($userCurrency);


        return $this->response->returnSuccess(['info' => $data]);


    }


    /**
     * 购买课程
     * @RequestMapping(path="buyCourses")
     */
    public function buyCourses()
    {

        $params = $this->request->post();

        // 验证参数
        $this->validate($params, [
            'num' => 'required',
            'payMethod' => 'required',
            'useNow' => 'required',
            'goodsId' => 'required',
        ]);

        $goodsInfo = ConsultantGood::where(['id' => $params['goodsId']])->first();
        if (is_null($goodsInfo)) {
            return $this->response->returnFail();
        }
        //生成主订单
        $orderNo = Order::getOrderNo();
        $userCurrency = UserDatum::where(['uid' => $this->uid()])->value('currency');


        //咨询师货币价格
        $consultantPrice = (string)round($params['num'] * $goodsInfo['price'], 2);

        //用户价格 目前暂时不考虑任何优惠折扣
        $usePrice = (string)ExchangeRate::exchangePrice($userCurrency, $goodsInfo['currency'], $consultantPrice);

        $priceUnit = (string)ExchangeRate::exchangePrice($userCurrency, $goodsInfo['currency'], $goodsInfo['price']);


        $data = [
            'uid' => $this->uid(),
            'order_no' => $orderNo,
            'goods_id' => $params['goodsId'],
            'aid' => $goodsInfo['uid'],
            'num' => $params['num'],
            'currency' => $userCurrency,
            'consultant_currency' => $goodsInfo['currency'],
            'price' => $usePrice,
            'price_unit' => $priceUnit,
            'buy_price_unit' => $priceUnit,
            'discount_amount' => '0.00',
            'coupon_amount' => '0.00',
            'pay_price' => $usePrice,
            'consultant_pay_price' => $consultantPrice,
            'buy_price' => $usePrice,
            'pay_price_unit' => '0.00',
            'service_amount' => '0.00',
            'tax_amount' => '0.00',
            'refundable_amount' => '0.00',
            'refund_amount' => '0.00',
            'pay_status' => 0,
            'status' => 0,
            'create_time' => time(),
            'pay_method' => $params['payMethod'],
            'user_now' => $params['useNow'],

        ];


        try {
            $id = Order::insertGetId($data);
            if ($id) {
                return $this->orderService->paymentIntent($id);
            } else {
                return $this->response->returnFail();
            }

        } catch (\Exception $e) {
            recordExceptionLog('购买订单出错', $e->getMessage());
            return $this->response->returnFail();
        }


    }


    /**
     * @RequestMapping(path="repayment")
     * @return ResponseInterface
     */
    public function repayment()
    {

        $params = $this->request->query();

        $this->validate($params, [
            'orderNo' => 'required'
        ]);

        $orderInfo = Order::where(['order_no' => $params['orderNo']])->first();

        if (is_null($orderInfo)) {
            return $this->response->returnFail();
        }

        return $this->orderService->paymentIntent($orderInfo['id']);

    }


    /**
     * @RequestMapping(path="reservationConsult")
     * @return ResponseInterface
     */
    public function reservationConsult()
    {

        $params = $this->request->post();

        $this->validate($params, [
            'wid' => 'required',
            'start' => 'required',
            'end' => 'required'
        ]);


        $workDayInfo = WorkDate::where(['id' => $params['wid']])->first();

        if (is_null($workDayInfo)) {
            return $this->response->returnFail(ErrorCode::WORK_DATE_NOT);
        }

        $goodsWhere[] = ['uid', '=', $this->uid()];
        $goodsWhere[] = ['status', '=', 0];
        $goodsWhere[] = ['aid', '=', $workDayInfo['uid']];

        if (isset($params['orderNo'])) {
            $goodsWhere[] = ['order_no', '=', $params['orderNo']];
        }

        $orderGoods = OrderGood::where($goodsWhere)->orderBy('id')->first();

        if (is_null($orderGoods)) {
            return $this->response->returnFail();
        }


        // 你的大时间区间
        $rangeStart = $workDayInfo['start'];

        if ($rangeStart < time()) {
            $rangeStart = time();
        }

        $rangeEnd = $workDayInfo['end'];

        if ($rangeStart >= $rangeEnd) {
            return $this->response->returnFail(ErrorCode::ORDER_WORK_DATE);
        }


        // 已被占用的时间段
        $where[] = ['wid', '=', $workDayInfo['id']];
        $where[] = ['end', '>', time()];

        $occupiedTimeSlots = WorkReservation::where($where)->orderBy('start')->get()->toArray();

        // 你希望选择的小区间
        $desiredStart = $params['start'];
        $desiredEnd = $params['end'];

        if ($desiredStart >= $desiredEnd) {
            return $this->response->returnFail(ErrorCode::WORK_TIME_FAIL);
        }

        $rel = $this->scheduleAlgorithm->isTimeSlotAvailable($rangeStart, $rangeEnd, $occupiedTimeSlots, $desiredStart, $desiredEnd);
        //可以预约开始进行预约 后期加锁 防止并发
        if ($rel) {


            Db::beginTransaction();
            try {

                $insertData = [
                    'uid' => $this->uid(),
                    'wid' => $params['wid'],
                    'start' => $desiredStart,
                    'end' => $desiredEnd,
                    'type' => 1,//用户预约
                    'status' => 0,//预约中
                    'create_time' => time()
                ];
                $timeId = WorkReservation::insertGetId($insertData);


                $orderReservationData = [
                    'uid' => $this->uid(),
                    'cid' => $workDayInfo['uid'],
                    'wid' => $workDayInfo['id'],
                    'tid' => $timeId,
                    'order_no' => $orderGoods['order_no'],
                    'status' => 1,//前期直接预约成功
                    'create_time' => time()
                ];

                //加入排班预约时间

                OrderReservation::insert($orderReservationData);

                //扣除 商品订单

                $orderGoodsData = [
                    'status' => 2,
                    'pre_start_time' => $desiredStart,
                    'pre_end_time' => $desiredEnd,
                    'pre_time' => time(),
                    'pre_confirm_time' => time(),
                ];

                OrderGood::where(['id' => $orderGoods['id']])->update($orderGoodsData);

                // todo 新下单 邮件 或手机号通知 待做

                //todo  判断在线状态推送系统 预约消息

                Db::commit();

                return $this->response->returnSuccess();
            } catch (\Exception $e) {

                Db::rollBack();
                return $this->response->returnFail();
            }


        } else {
            return $this->response->returnFail(ErrorCode::WORK_TIME_FAIL);
        }


    }


    /**
     * @RequestMapping(path="goodsOrderList")
     * @return ResponseInterface
     */
    public function goodsOrderList()
    {

        $where[] = ['a.uid', '=', $this->uid()];
        $where[] = ['a.delete_time', '=', 0];

        $type = $this->request->query('type');

        $status = [0, 1, 2, 3, 4];
        switch ($type) {
            case 1://待完成待使用
                $status = [0, 2];
                break;
            case 2://
                $status = [1];
                break;
            case 3:
                $status = [1];
                $where[] = ['a.evaluate_status', '=', 2];
                break;
        }


        $list = OrderGood::goodsOrderList($where, $status);

        return $this->response->returnSuccess(['list' => $list]);


    }

    /**
     * @RequestMapping(path="orderList")
     * @return ResponseInterface
     */
    public function orderList()
    {

        $where[] = ['a.uid', '=', $this->uid()];
        $list = Order::getOrderList($where);

        foreach ($list['list'] as $k => $v) {
            $list['list'][$k]['countdown'] = 0;
            $time = $v['expire_time'] - time();
            if ($time >= 0) {
                $list['list'][$k]['countdown'] = intval($time);
            }

        }
        return $this->response->returnSuccess(['list' => $list]);

    }

    /**
     * @RequestMapping(path="delGoodsOrder")
     * @return ResponseInterface
     */
    public function delGoodsOrder()
    {
        $params = $this->request->post();

        $this->validate($params, [
            'orderNo' => 'required'
        ]);

        $goodsOrder = OrderGood::where(['order_no' => $params['orderNo'], 'uid' => $this->uid(), 'status' => 1])->first();

        if (is_null($goodsOrder)) {
            return $this->response->returnFail();
        }

        $updateData = [
            'delete_time' => time(),
            'status' => 4
        ];

        $rel = OrderGood::where(['order_no' => $params['orderNo']])->update($updateData);

        if ($rel) {
            return $this->response->returnSuccess();
        } else {
            return $this->response->returnFail();
        }

    }


    /**
     *
     * @RequestMapping(path="reviewOrder")
     * @return ResponseInterface
     */
    public function reviewOrder()
    {

        $params = $this->request->post();

        $this->validate($params, [
            'orderNo' => "required",
            'rating' => 'required',
            'comment' => 'required',
            'label' => 'required',
            'anonymous' => 'required'
        ]);


        //查找评价的商品订单
        $goodsOrder = OrderGood::where(['order_no' => $params['orderNo'], 'uid' => $this->uid(), 'status' => 1, 'evaluate_status' => 2])->first();

        if (is_null($goodsOrder)) {
            return $this->response->returnFail();
        }

        $insertData = [
            'order_id' => $goodsOrder['id'],
            'uid' => $goodsOrder['uid'],
            'aid' => $goodsOrder['aid'],
            'rating' => $params['rating'],
            'comment' => $params['comment'],
            'label' => $params['label'],
            'anonymous' => $params['anonymous'],
            'create_time' => time()
        ];

        Db::beginTransaction();
        try {
            $rel = OrderReview::insert($insertData);
            OrderGood::where(['order_no' => $params['orderNo'], 'uid' => $this->uid(), 'status' => 1, 'evaluate_status' => 2])
                ->update(['evaluate_status' => 1]);


            Db::commit();

            return $this->response->returnSuccess();

        } catch (\Exception $e) {

            Db::rollBack();
            return $this->response->returnFail();
        }


    }


    /**
     * @RequestMapping(path="reviewLabelList")
     * @return ResponseInterface
     */
    public function reviewLabelList(){


        $lang = getLang();

        $labelList = ReviewLabelTran::from('review_label as a')
            ->leftJoin('review_label_trans as b','a.id','=','b.review_label_id')
            ->where(['b.lang'=>$lang])
            ->select(['a.id','b.name','a.type'])->get()->toArray();

        return $this->response->returnSuccess(['list'=>$labelList]);


    }

}
